package lock;

import java.util.concurrent.*;

/**
 * 案例：多个线程交替打印，从0打印到100
 */
public class SemaphoreTest3 {

    public static void main(String[] args) {
        print(0, 100, 2, 10);
    }

    /**
     * 使用n个线程交替打印，打印区间[start, end]
     * @param start 打印区间起始点
     * @param end 打印区间终止点
     * @param n 使用的线程数
     * @param waitMillis 打印间隔时间
     */
    public static void print(final int start, final int end, final int n, final long waitMillis) {
        Semaphore[] semaphores = new Semaphore[n];
        semaphores[0] = new Semaphore(1);
        for (int i = 1;i < n;i++)
            semaphores[i] = new Semaphore(0);
//        ExecutorService executorService = Executors.newFixedThreadPool(n);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(n, n, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
        for (int i = 0;i < n;i++) {
            final int fi = i;
            threadPoolExecutor.execute(() -> {
                try {
                    int printNum = start + fi;
                    while (printNum <= end) { //当要打印的数超过end时则直接退出循环 不阻塞
                        semaphores[fi].acquire(); //阻塞等待上一个线程释放信号资源
                        System.out.println(printNum);
                        Thread.sleep(waitMillis);
                        if (fi + 1 < n) semaphores[fi+1].release(); //打印完后释放下一个信号资源以唤醒下一个线程进行打印
                        else semaphores[0].release(); //最后一个线程则唤醒第一个线程
                        printNum += n; //下一个要打印的数
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        threadPoolExecutor.shutdown();//记得关闭线程池
    }
}
